using System.ComponentModel;
using System.Runtime.Serialization;

using SharpGL.Enumerations;

namespace SharpGL.OpenGLAttributes
{
    /// <summary>
    /// This class has all the settings you can edit for fog.
    /// </summary>
    [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
    [DataContract(/*IsReference = true, */Name = "EnableAttributes", Namespace = "SharpGL.SceneGraph")]
    public class EnableAttributes : OpenGLAttributes
    {
        #region Private Consts

        private static readonly AttributeMask attributeMask = AttributeMask.Enable;

        #endregion Private Consts

        #region Private Fields

        [DataMember()]
        private bool? enableAlphaTest;
        [DataMember()]
        private bool? enableAutoNormal;
        [DataMember()]
        private bool? enableBlend;
        [DataMember()]
        private bool? enableColorMaterial;
        [DataMember()]
        private bool? enableCullFace;
        [DataMember()]
        private bool? enableDepthTest;
        [DataMember()]
        private bool? enableDither;
        [DataMember()]
        private bool? enableFog;
        [DataMember()]
        private bool? enableLighting;
        [DataMember()]
        private bool? enableLineSmooth;
        [DataMember()]
        private bool? enableLineStipple;
        [DataMember()]
        private bool? enableColorLogicOp;
        [DataMember()]
        private bool? enableIndexLogicOp;
        [DataMember()]
        private bool? enableNormalize;
        [DataMember()]
        private bool? enablePointSmooth;
        [DataMember()]
        private bool? enablePolygonOffsetLine;
        [DataMember()]
        private bool? enablePolygonOffsetFill;
        [DataMember()]
        private bool? enablePolygonOffsetPoint;
        [DataMember()]
        private bool? enablePolygonSmooth;
        [DataMember()]
        private bool? enablePolygonStipple;
        [DataMember()]
        private bool? enableScissorTest;
        [DataMember()]
        private bool? enableStencilTest;
        [DataMember()]
        private bool? enableTexture1D;
        [DataMember()]
        private bool? enableTexture2D;

        #endregion Private Fields

        #region Protected Methods

        protected override void OnDeserializing()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Protected Methods

        #region Public Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="EnableAttributes"/> class.
        /// </summary>
        public EnableAttributes()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Returns true if any attributes are set.
        /// </summary>
        /// <returns>
        /// True if any attributes are set
        /// </returns>
        public override bool AreAnyAttributesSet()
        {
            return
                enableAlphaTest.HasValue ||
                enableAutoNormal.HasValue ||
                enableBlend.HasValue ||
                enableColorMaterial.HasValue ||
                enableCullFace.HasValue ||
                enableDepthTest.HasValue ||
                enableDither.HasValue ||
                enableFog.HasValue ||
                enableLighting.HasValue ||
                enableLineSmooth.HasValue ||
                enableLineStipple.HasValue ||
                enableColorLogicOp.HasValue ||
                enableIndexLogicOp.HasValue ||
                enableNormalize.HasValue ||
                enablePointSmooth.HasValue ||
                enablePolygonOffsetLine.HasValue ||
                enablePolygonOffsetFill.HasValue ||
                enablePolygonOffsetPoint.HasValue ||
                enablePolygonSmooth.HasValue ||
                enablePolygonStipple.HasValue ||
                enableScissorTest.HasValue ||
                enableStencilTest.HasValue ||
                enableTexture1D.HasValue ||
                enableTexture2D.HasValue;

        }

        /// <summary>
        /// Reset all attributes to unset state.
        /// </summary>
        public override void ResetAllAttributes()
        {
            EnableAlphaTest = null;
            EnableAutoNormal = null;
            EnableBlend = null;
            EnableColorMaterial = null;
            EnableCullFace = null;
            EnableDepthTest = null;
            EnableDither = null;
            EnableFog = null;
            EnableLighting = null;
            EnableLineSmooth = null;
            EnableLineStipple = null;
            EnableColorLogicOp = null;
            EnableIndexLogicOp = null;
            EnableNormalize = null;
            EnablePointSmooth = null;
            EnablePolygonOffsetLine = null;
            EnablePolygonOffsetFill = null;
            EnablePolygonOffsetPoint = null;
            EnablePolygonSmooth = null;
            EnablePolygonStipple = null;
            EnableScissorTest = null;
            EnableStencilTest = null;
            EnableTexture1D = null;
            EnableTexture2D = null;
        }

        /// <summary>
        /// Sets the attributes.
        /// </summary>
        /// <param name="gl">The OpenGL instance.</param>
        public override void SetAttributes(OpenGL gl)
        {
            if (enableAlphaTest.HasValue) gl.EnableIf(OpenGL.GL_ALPHA_TEST, enableAlphaTest.Value);
            if (enableAutoNormal.HasValue) gl.EnableIf(OpenGL.GL_AUTO_NORMAL, enableAutoNormal.Value);
            if (enableBlend.HasValue) gl.EnableIf(OpenGL.GL_BLEND, enableBlend.Value);
            if (enableColorMaterial.HasValue) gl.EnableIf(OpenGL.GL_COLOR_MATERIAL, enableColorMaterial.Value);
            if (enableCullFace.HasValue) gl.EnableIf(OpenGL.GL_CULL_FACE, enableCullFace.Value);
            if (enableDepthTest.HasValue) gl.EnableIf(OpenGL.GL_DEPTH_TEST, enableDepthTest.Value);
            if (enableDither.HasValue) gl.EnableIf(OpenGL.GL_DITHER, enableDither.Value);
            if (enableFog.HasValue) gl.EnableIf(OpenGL.GL_FOG, enableFog.Value);
            if (enableLighting.HasValue) gl.EnableIf(OpenGL.GL_LIGHTING, enableLighting.Value);
            if (enableLineSmooth.HasValue) gl.EnableIf(OpenGL.GL_LINE_SMOOTH, enableLineSmooth.Value);
            if (enableLineStipple.HasValue) gl.EnableIf(OpenGL.GL_LINE_STIPPLE, enableLineStipple.Value);
            if (enableColorLogicOp.HasValue) gl.EnableIf(OpenGL.GL_COLOR_LOGIC_OP, enableColorLogicOp.Value);
            if (enableIndexLogicOp.HasValue) gl.EnableIf(OpenGL.GL_INDEX_LOGIC_OP, enableIndexLogicOp.Value);
            if (enableNormalize.HasValue) gl.EnableIf(OpenGL.GL_NORMALIZE, enableNormalize.Value);
            if (enablePointSmooth.HasValue) gl.EnableIf(OpenGL.GL_POINT_SMOOTH, enablePointSmooth.Value);
            if (enablePolygonOffsetLine.HasValue) gl.EnableIf(OpenGL.GL_POLYGON_OFFSET_LINE, enablePolygonOffsetLine.Value);
            if (enablePolygonOffsetFill.HasValue) gl.EnableIf(OpenGL.GL_POLYGON_OFFSET_FILL, enablePolygonOffsetFill.Value);
            if (enablePolygonOffsetPoint.HasValue) gl.EnableIf(OpenGL.GL_POLYGON_OFFSET_POINT, enablePolygonOffsetPoint.Value);
            if (enablePolygonSmooth.HasValue) gl.EnableIf(OpenGL.GL_POLYGON_SMOOTH, enablePolygonSmooth.Value);
            if (enablePolygonStipple.HasValue) gl.EnableIf(OpenGL.GL_POLYGON_STIPPLE, enablePolygonStipple.Value);
            if (enableScissorTest.HasValue) gl.EnableIf(OpenGL.GL_SCISSOR_TEST, enableScissorTest.Value);
            if (enableStencilTest.HasValue) gl.EnableIf(OpenGL.GL_STENCIL, enableStencilTest.Value);
            if (enableTexture1D.HasValue) gl.EnableIf(OpenGL.GL_TEXTURE_1D, enableTexture1D.Value);
            if (enableTexture2D.HasValue) gl.EnableIf(OpenGL.GL_TEXTURE_2D, enableTexture2D.Value);
        }

        #endregion Public Methods

        #region Public Properties

        /// <summary>
        /// Gets or sets the enable alpha test.
        /// </summary>
        /// <value>
        /// The enable alpha test.
        /// </value>
        [Description("EnableAlphaTest"), Category("Enable attributes")]
        public bool? EnableAlphaTest
        {
            get { return enableAlphaTest; }
            set
            {
                if (enableAlphaTest != value)
                {
                    enableAlphaTest = value;

                    NotifyPropertyChanged("EnableAlphaTest");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable auto normal.
        /// </summary>
        /// <value>
        /// The enable auto normal.
        /// </value>
        [Description("EnableAutoNormal"), Category("Enable attributes")]
        public bool? EnableAutoNormal
        {
            get { return enableAutoNormal; }
            set
            {
                if (enableAutoNormal != value)
                {
                    enableAutoNormal = value;

                    NotifyPropertyChanged("EnableAutoNormal");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable blend.
        /// </summary>
        /// <value>
        /// The enable blend.
        /// </value>
        [Description("EnableBlend"), Category("Enable attributes")]
        public bool? EnableBlend
        {
            get { return enableBlend; }
            set
            {
                if (enableBlend != value)
                {
                    enableBlend = value;

                    NotifyPropertyChanged("EnableBlend");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable color material.
        /// </summary>
        /// <value>
        /// The enable color material.
        /// </value>
        [Description("EnableColorMaterial"), Category("Enable attributes")]
        public bool? EnableColorMaterial
        {
            get { return enableColorMaterial; }
            set
            {
                if (enableColorMaterial != value)
                {
                    enableColorMaterial = value;

                    NotifyPropertyChanged("EnableColorMaterial");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable cull face.
        /// </summary>
        /// <value>
        /// The enable cull face.
        /// </value>
        [Description("EnableCullFace"), Category("Enable attributes")]
        public bool? EnableCullFace
        {
            get { return enableCullFace; }
            set
            {
                if (enableCullFace != value)
                {
                    enableCullFace = value;

                    NotifyPropertyChanged("EnableCullFace");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable depth test.
        /// </summary>
        /// <value>
        /// The enable depth test.
        /// </value>
        [Description("EnableDepthTest"), Category("Enable attributes")]
        public bool? EnableDepthTest
        {
            get { return enableDepthTest; }
            set
            {
                if (enableDepthTest != value)
                {
                    enableDepthTest = value;

                    NotifyPropertyChanged("EnableDepthTest");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable dither.
        /// </summary>
        /// <value>
        /// The enable dither.
        /// </value>
        [Description("EnableDither"), Category("Enable attributes")]
        public bool? EnableDither
        {
            get { return enableDither; }
            set
            {
                if (enableDither != value)
                {
                    enableDither = value;

                    NotifyPropertyChanged("EnableDither");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable fog.
        /// </summary>
        /// <value>
        /// The enable fog.
        /// </value>
        [Description("EnableFog"), Category("Enable attributes")]
        public bool? EnableFog
        {
            get { return enableFog; }
            set
            {
                if (enableFog != value)
                {
                    enableFog = value;

                    NotifyPropertyChanged("EnableFog");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable lighting.
        /// </summary>
        /// <value>
        /// The enable lighting.
        /// </value>
        [Description("EnableLighting"), Category("Enable attributes")]
        public bool? EnableLighting
        {
            get { return enableLighting; }
            set
            {
                if (enableLighting != value)
                {
                    enableLighting = value;

                    NotifyPropertyChanged("EnableLighting");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable line smooth.
        /// </summary>
        /// <value>
        /// The enable line smooth.
        /// </value>
        [Description("EnableLineSmooth"), Category("Enable attributes")]
        public bool? EnableLineSmooth
        {
            get { return enableLineSmooth; }
            set
            {
                if (enableLineSmooth != value)
                {
                    enableLineSmooth = value;

                    NotifyPropertyChanged("EnableLineSmooth");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable line stipple.
        /// </summary>
        /// <value>
        /// The enable line stipple.
        /// </value>
        [Description("EnableLineStipple"), Category("Enable attributes")]
        public bool? EnableLineStipple
        {
            get { return enableLineStipple; }
            set
            {
                if (enableLineStipple != value)
                {
                    enableLineStipple = value;

                    NotifyPropertyChanged("EnableLineStipple");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable color logic op.
        /// </summary>
        /// <value>
        /// The enable color logic op.
        /// </value>
        [Description("EnableColorLogicOp"), Category("Enable attributes")]
        public bool? EnableColorLogicOp
        {
            get { return enableColorLogicOp; }
            set
            {
                if (enableColorLogicOp != value)
                {
                    enableColorLogicOp = value;

                    NotifyPropertyChanged("EnableColorLogicOp");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable index logic op.
        /// </summary>
        /// <value>
        /// The enable index logic op.
        /// </value>
        [Description("EnableIndexLogicOp"), Category("Enable attributes")]
        public bool? EnableIndexLogicOp
        {
            get { return enableIndexLogicOp; }
            set
            {
                if (enableIndexLogicOp != value)
                {
                    enableIndexLogicOp = value;

                    NotifyPropertyChanged("EnableIndexLogicOp");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable normalize.
        /// </summary>
        /// <value>
        /// The enable normalize.
        /// </value>
        [Description("EnableNormalize"), Category("Enable attributes")]
        public bool? EnableNormalize
        {
            get { return enableNormalize; }
            set
            {
                if (enableNormalize != value)
                {
                    enableNormalize = value;

                    NotifyPropertyChanged("EnableNormalize");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable point smooth.
        /// </summary>
        /// <value>
        /// The enable point smooth.
        /// </value>
        [Description("EnablePointSmooth"), Category("Enable attributes")]
        public bool? EnablePointSmooth
        {
            get { return enablePointSmooth; }
            set
            {
                if (enablePointSmooth != value)
                {
                    enablePointSmooth = value;

                    NotifyPropertyChanged("EnablePointSmooth");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable polygon offset line.
        /// </summary>
        /// <value>
        /// The enable polygon offset line.
        /// </value>
        [Description("EnablePolygonOffsetLine"), Category("Enable attributes")]
        public bool? EnablePolygonOffsetLine
        {
            get { return enablePolygonOffsetLine; }
            set
            {
                if (enablePolygonOffsetLine != value)
                {
                    enablePolygonOffsetLine = value;

                    NotifyPropertyChanged("EnablePolygonOffsetLine");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable polygon offset fill.
        /// </summary>
        /// <value>
        /// The enable polygon offset fill.
        /// </value>
        [Description("EnablePolygonOffsetFill"), Category("Enable attributes")]
        public bool? EnablePolygonOffsetFill
        {
            get { return enablePolygonOffsetFill; }
            set
            {
                if (enablePolygonOffsetFill != value)
                {
                    enablePolygonOffsetFill = value;

                    NotifyPropertyChanged("EnablePolygonOffsetFill");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable polygon offset point.
        /// </summary>
        /// <value>
        /// The enable polygon offset point.
        /// </value>
        [Description("EnablePolygonOffsetPoint"), Category("Enable attributes")]
        public bool? EnablePolygonOffsetPoint
        {
            get { return enablePolygonOffsetPoint; }
            set
            {
                if (enablePolygonOffsetPoint != value)
                {
                    enablePolygonOffsetPoint = value;

                    NotifyPropertyChanged("EnablePolygonOffsetPoint");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable polygon smooth.
        /// </summary>
        /// <value>
        /// The enable polygon smooth.
        /// </value>
        [Description("EnablePolygonSmooth"), Category("Enable attributes")]
        public bool? EnablePolygonSmooth
        {
            get { return enablePolygonSmooth; }
            set
            {
                if (enablePolygonSmooth != value)
                {
                    enablePolygonSmooth = value;

                    NotifyPropertyChanged("EnablePolygonSmooth");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable polygon stipple.
        /// </summary>
        /// <value>
        /// The enable polygon stipple.
        /// </value>
        [Description("EnablePolygonStipple"), Category("Enable attributes")]
        public bool? EnablePolygonStipple
        {
            get { return enablePolygonStipple; }
            set
            {
                if (enablePolygonStipple != value)
                {
                    enablePolygonStipple = value;

                    NotifyPropertyChanged("EnablePolygonStipple");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable scissor test.
        /// </summary>
        /// <value>
        /// The enable scissor test.
        /// </value>
        [Description("EnableScissorTest"), Category("Enable attributes")]
        public bool? EnableScissorTest
        {
            get { return enableScissorTest; }
            set
            {
                if (enableScissorTest != value)
                {
                    enableScissorTest = value;

                    NotifyPropertyChanged("EnableScissorTest");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable stencil test.
        /// </summary>
        /// <value>
        /// The enable stencil test.
        /// </value>
        [Description("EnableStencilTest"), Category("Enable attributes")]
        public bool? EnableStencilTest
        {
            get { return enableStencilTest; }
            set
            {
                if (enableStencilTest != value)
                {
                    enableStencilTest = value;

                    NotifyPropertyChanged("EnableStencilTest");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable texture 1D.
        /// </summary>
        /// <value>
        /// The enable texture 1D.
        /// </value>
        [Description("EnableTexture1D"), Category("Enable attributes")]
        public bool? EnableTexture1D
        {
            get { return enableTexture1D; }
            set
            {
                if (enableTexture1D != value)
                {
                    enableTexture1D = value;

                    NotifyPropertyChanged("EnableTexture1D");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable texture 2D.
        /// </summary>
        /// <value>
        /// The enable texture 2D.
        /// </value>
        [Description("EnableTexture2D"), Category("Enable attributes")]
        public bool? EnableTexture2D
        {
            get { return enableTexture2D; }
            set
            {
                if (enableTexture2D != value)
                {
                    enableTexture2D = value;

                    NotifyPropertyChanged("EnableTexture2D");
                }
            }
        }

        #endregion Public Properties
    }
}
